// @Author EthanScriptOn
// @Desc
package common

import (
	"errors"
	"gitee.com/fatzeng/srf_switch_basic_components/node"
	"gitee.com/fatzeng/srf_switch_basic_components/proxy"
	"gitee.com/fatzeng/srf_switch_basic_components/util"
	"gitee.com/fatzeng/srf_switch_config/config_context"
	"sync"
	"sync/atomic"
)

type FundamentalComponent struct {
	done uint32
	mu   sync.Mutex
}

func (f *FundamentalComponent) HandleCallErr(methodCall *util.MethodCall, err error) error {
	if err != nil {
		return err
	}
	if callErr := methodCall.GetError(); callErr != nil {
		return callErr
	}
	return nil
}

func (f *FundamentalComponent) GetCurrentReferenceProxy(ctx *config_context.ConfigInitializationContext) (*proxy.Proxy, error) {
	recentlyStore, err := ctx.GetRecentlyCurrentReferenceProxyStore()
	if err != nil {
		return nil, err
	}
	holderNode, ok := recentlyStore.(*node.CurrentReferenceHolderNode)
	if !ok {
		return nil, errors.New("currentReferenceProxyStore type error need *config_node.CurrentReferenceHolderNode")
	}
	return holderNode.GetCurrentReferenceProxy(), nil
}

func (f *FundamentalComponent) GetCurrentReference(ctx *config_context.ConfigInitializationContext) (interface{}, error) {
	currentReference, err := f.GetCurrentReferenceProxy(ctx)
	if err != nil {
		return nil, err
	}
	return currentReference, nil
}

func (f *FundamentalComponent) doExit() {
	if atomic.LoadUint32(&f.done) == 0 {
		return
	}
	atomic.StoreUint32(&f.done, 0)
}

func (f *FundamentalComponent) doEnter() bool {
	canEnter := atomic.LoadUint32(&f.done) == 0
	if canEnter {
		mu := &f.mu
		_ = util.LockWithSync(mu.Lock, mu.Unlock, func() error {
			if f.done == 0 {
				atomic.StoreUint32(&f.done, 1)
			} else {
				canEnter = false
			}
			return nil
		})
	}
	return canEnter
}
